The checkAssociationSpecialization and checkFeatureEndSpecialization constraints require that an Association specialize the base Association Links::Link (see
9.2.3.2.3
) and that its associationEnds subset Links::Link::participant. In addition, the validateFeatureEndMultiplicity constraint requires that the associationEnds must have multiplicity 1..1. These constraints essentially require an N-ary Association to have the form (with implied relationships included):
assoc A specializes Links::Link {
end feature e1[1..1] subsets Links::Link::participant;
end feature e2[1..1] subsets Links::Link::participant;
...
end feature eN[1..1] subsets Links::Link::participant;
} The Link instance for an Association is thus a tuple of participants, where each participant is a single value of an associationEnd of the Association. Note also that the Feature Link::participant is declared readonly, meaning that the participants in a link cannot change once the link is created.
The checkFeatureEndRedefinition constraint requires that, if an Association has an ownedSubclassification to another Association, then its associationEnds redefine the associationEnds of the superclassifier Association. In this case, the subclassifier Association will indirectly specialize Link through a chain of Subclassifications, and each of its associationEnds will indirectly subset Links::participant through a chain of Redefinition and Subsetting.
The checkAssociationBinarySpecialization constraint requires that a binary Association (one with exactly two associationEnds) specialize Links::BinaryLink. BinaryLink specializes Link to have exactly two participants corresponding to two ends called source and target. As required by the checkFeatureEndRedefinition constraint, the first associationEnd of a binary Association will redefine Links::BinaryLink::source and its second associationEnd will redefine Links::BinaryLink::target.
assoc B specializes Links::BinaryLink {
end feature e1 redefines Links::BinaryLink::source;
end feature e2 redefines Links::BinaryLink::target;
} Note that, as associationEnds of BinaryLink, source and target already have multiplicities of 1..1, which ensures that the ends of any binary Association do too.
A binary Association can also specify cross features for one or both of its associationEnds using CrossSubsetting. Such a cross feature must be a feature of the type of the other associationEnd than the one for the cross feature.
The validateCrossSubsettingCrossedFeature constraint requires that the target of a CrossSubsetting be a feature chain consisting of the other associationEnd and the cross feature. CrossSubsetting is a kind of Subsetting, so it semantically requires that the value of an associationEnd be one of the values of the cross feature for the other associationEnd.
This also means that, if an associationEnd of a binary Association has a cross feature, then the cross-feature multiplicity applies to each set of instances (links) of the Association that have the same (singleton) value for the associationEnd. Cross feature uniqueness and ordering apply to the collection of values of the other associationEnd in each of those link sets, preventing duplication in each collection and ordering them to form a sequence.
For example, the binary Association B1 below specifies cross features for both its ends (without implied relationships included):
classifier T1 {
feature e2_cross[0..1] : T2;
}
classifier T2 {
feature e1_cross[1..4] nonunique ordered : T1;
}
assoc B1 {
end feature e1 : T1 crosses e2.e1_cross;
end feature e2 : T2 crosses e1.e2_cross;
} The multiplicities specified for e1_cross and e2_cross then mean that:
- For each value of
e1_cross, there is at most one instance of B1 for which e1 has that value and e2 has the corresponding value of e2_cross (multiplicity 0..1). - For each value of
e2_cross, there are one to four instances of B1 for which e2 has that value and e1 has the corresponding value of e1_cross (multiplicity 1..4). Further, there may be more than one of these instances with the same value of e1 (nonunique) and the instances have an implied ordering (ordered).
Note. Ordering and uniqueness are irrelevant on the associationEnds themselves, since they must always have multiplicity 1..1.
Note that cross features impose only necessary conditions on the instances of an Association, which do not require existence of instances of the Association for all values of its cross features. To make these conditions also sufficient, requiring existence of these instances, the Association must have isSufficient = true (see
8.3.3.1.10
). For example, if B1 above has isSufficient = true, then an instance t1 of T1 having a value t2 for e2_cross is sufficient to require that an instance of B1 exist linking t1 to t2 and, therefore, that t1 is a value of e1_cross for t2.
assoc all B1 { // "all" declares isSufficient = true
end feature e1 : T1 crosses e2.e1_cross;
end feature e2 : T2 crosses e1.e2_cross;
} Cross features may also be directly owned by the corresponding associationEnd. The checkFeatureOwnedCrossFeatureTypeFeaturing constraint requires such an owned cross feature (for a binary Association) be featured by the type of the other associationEnd (which means it must be owned by the associationEnd via OwnedMembership but not FeatureMembership). Further, the checkFeatureCrossingSpecialization constraint requires that the associationEnd has a CrossSubsetting that targets a feature chain whose first Feature is the other associationEnd and whose second Feature is the owned cross feature.
An owned cross feature may be declared with the declaration of the corresponding associationEnd. For example, the following binary Association declaration (the cross feature names are optional, but they are included here for convenience of reference):
assoc B2
end e1_cross [1..4] nonunique ordered feature e1 : T1;
end e2_cross [0..1] feature e2 : T2;
} is parsed (with implied relationships included) as:
assoc B2 specializes Links::BinaryLink {
end feature e1 : T1 redefines Links::BinaryLink::source;
crosses e2.e1_cross {
member feature e1_cross[1..4] nonunique ordered : T1
featured by T2;
}
end feature e2 : T2 redefines Links::BinaryLink::target;
crosses e1.e2_cross {
member feature e2_cross[0..1] : T2 featured by T1;
}
} Note. The feature chain notations e2.e1_cross and e2.e1_cross in the above notional equivalent will actually not parse, because e1_cross is not in the namespace of e2 and e2_cross is not in the namespace of e1. However, the Features meet the semantic requirements for a feature chain (i.e., the type of the first Feature is the featuringType of the second Feature), so the construct is valid in the abstract syntax.
An Association with three or more associationEnds may also have ends with cross features, but, in this case, the cross features must be owned by their corresponding associationEnds. For example, the ternary Association
assoc Ternary {
end a_cross[1] feature a[1] : A;
end b_cross[0..2] feature b[1] : B;
end c_cross[*] nonunique ordered feature c[1] : C;
} is effectively parsed (including implied relationships) as
assoc Ternary specializes Links::Link {
end feature a[1] : A subsets Links::Link::participant
crosses b_c.a_cross {
member feature b_c : B_C featured by Ternary;
member feature B_C : C featured by B;
member feature a_cross[1] : A featured by B_C;
}
end feature b[1] : B subsets Links::Link::participant
crosses a_c.b_cross {
member feature a_c : A_C featured by Ternary;
member feature A_C : C featured by A;
member feature b_cross[0..2] : B featured by A_C;
}
end feature c[1] : C subsets Links::Link::participant
crosses a_b.c_cross {
member feature a_b : A_B featured by Ternary;
member feature A_B : C featured by B;
member feature c_cross[*] : C featured by A_B;
}
} Consider specifically the assocationEnd a in the above Association. Since the Association is not binary, there is no longer a single other assocationEnd to a. So, in order to satisfy the checkFeatureOwnedCrossFeatureTypeFeaturing constraint, the cross feature a_cross is featured by the Feature B_C, which is constructed as being typed by C and featured by B. According to the Core semantics for Features (see
8.4.3.4
), the Feature B_C is (minimally) interpreted as having instances that are pairs of instances of B and C, in that order. That is, the feature can be considered to semantically represent a Cartesian product of the set of instances of B and the set of instances of C. The associationEnd a then has a CrossSubsetting of a feature chain that starts with the Feature b_c, which is typed by B_C, followed by the cross feature a_cross, which is featured by B_C. As a result, the values of a_cross for each instance of Ternary are the values of the associationEnd a on all the instances of Ternary that have the same values for the other two associationEnds.
Note also that the Features B_C and b_c are shown above as nested in the associationEnd a for purposes of presentation in the textual notation. However, when added with the implied relationships needed to satisfy semantic constraints, these Features are actually ownedRelatedElements of, respectively, the implied TypeFeaturing relationship on owned cross feature a_cross and the first FeatureChaining relationship in the target feature chain of the implied CrossSubsetting relationship on the associationEnd a.
That is, the implied abstract syntax ownership structure is:
(The names B_C and b_c are included here for correspondence to the earlier textual notation presentation. These Features would not be expected to be named in an actual implementation.)
Similar syntax and semantics apply to all three of the associationEnds of Ternary. Each instance of Ternary consists of three participants, one value for each of the associationEnds a, b and c. But the multiplicities specified for the owned cross features of the associationEnds then assert that:
1. For any specific values of b and c, there must be exactly one instance of Ternary, with the single value allowed for a.
2. For any specific values of a and c, there may be up to two instances of Ternary, all of which must have different values for b (default uniqueness).
3. For any specific values of a and b, there may be any number of instance of Ternary, which are ordered and allow repeated values for c.
This approach is applied to any N-ary Association with N of 3 or greater by extending the pattern for representing a Cartesian product of Classifiers using a Feature to any number of Classifiers. The operation Feature::isCartesianProduct checks whether a Feature meets the pattern for representing a Cartesian product. If so, then the operation Feature::asCartesianProduct returns the ordered list of Classifiers in the product. (See
8.3.3.3.4
for the specifications of these operations.)
This gives the following general semantics for owned cross feature multiplicity: For an Association with N associationEnds, with N of 2 or greater, consider the i-th associationEnd ei. The multiplicity of the owned cross feature of ei applies to each set of instances of the Association that have the same (singleton) values for each of the N-1 associationEnds other than ei. Uniqueness and ordering of the owned cross feature apply to the collection of values of ei in each of those link sets, preventing duplication in each collection and ordering them to form a sequence.
As described previously, the checkFeatureEndRedefinition constraint requires the associationEnds of an specialized Association to redefine the ends of the Associations it specializes. If a redefining associationEnd has an owned cross feature, the checkFeatureOwnedCrossFeatureRedefinitionSpecialization constraint further requires that the owned cross feature of the redefining associationEnd must subset the cross feature of the redefined associationEnd. Note that this constraint must be satisfied even of the cross feature of the redefined associationEnd is not owned by that associationEnd.
For example, consider the following specialization of the Association B2 shown earlier:
assoc B2a specializes B2 {
end e1a_cross [0..2] nonunique ordered feature e1a : T1;
end e2a_cross [1..1] feature e2a : T2;
} This is parsed (with implied relationships included) as:
assoc B2a specializes B2 {
end feature e1a : T1 redefines B2::e1
crosses e2a.e1a_cross {
member feature e1a_cross[0..2] nonunique ordered : T1
subsets B2::e1::e1_cross featured by T2;
}
end feature e2 : T2 redefines B2::e2
crosses e1.e2a_cross {
member feature e2a_cross[1..1] : T2
subsets B2::e2::e2_cross featured by T1;
}
}Type